import { ref } from "vue"
import { Base64 } from "js-base64";
export function wordsDraw(optinos = {}) {
  const data = ref(null)
  const config = {
    width: 60,
    height: 60,
    padding: 8,
    wordsColor: "#000000",
    wordsColorDraw: '#dddddd',
    ...optinos
  }
  const subtract = (p1, p2) => ({
    x: p1.x - p2.x,
    y: p1.y - p2.y,
  });
  const magnitude = (point) => Math.sqrt(Math.pow(point.x, 2) + Math.pow(point.y, 2));
  const distance = (point1, point2) => magnitude(subtract(point1, point2));
  const length = (points) => {
    let lastPoint = points[0];
    const pointsSansFirst = points.slice(1);
    return pointsSansFirst.reduce((acc, point) => {
      const dist = distance(point, lastPoint);
      lastPoint = point;
      return acc + dist;
    }, 0);
  };
  const getLength = (points) => {
    return length(points);
  };

  const round = (point, precision = 1) => {
    const multiplier = precision * 10;
    return {
      x: Math.round(multiplier * point.x) / multiplier,
      y: Math.round(multiplier * point.y) / multiplier,
    };
  };

  function getPathString(points, close = false) {
    const start = round(points[0]);
    const remainingPoints = points.slice(1);
    let pathString = `M ${start.x} ${start.y}`;
    remainingPoints.forEach((point) => {
      const roundedPoint = round(point);
      pathString += ` L ${roundedPoint.x} ${roundedPoint.y}`;
    });

    if (close) {
      pathString += "Z";
    }

    return pathString;
  }

  const _filterParallelPoints = (points) => {
    if (points.length < 3) return points;
    const filteredPoints = [points[0], points[1]];
    points.slice(2).forEach((point) => {
      const numFilteredPoints = filteredPoints.length;
      const curVect = subtract(point, filteredPoints[numFilteredPoints - 1]);
      const prevVect = subtract(
        filteredPoints[numFilteredPoints - 1],
        filteredPoints[numFilteredPoints - 2]
      ); // this is the z coord of the cross-product. If this is 0 then they're parallel

      const isParallel = curVect.y * prevVect.x - curVect.x * prevVect.y === 0;

      if (isParallel) {
        filteredPoints.pop();
      }

      filteredPoints.push(point);
    });
    return filteredPoints;
  };
  const _extendPointOnLine = (p1, p2, dist) => {
    const vect = subtract(p2, p1);
    const norm = dist / magnitude(vect);
    return {
      x: p2.x + norm * vect.x,
      y: p2.y + norm * vect.y,
    };
  };

  const extendStart = (points, dist) => {
    const filteredPoints = _filterParallelPoints(points);

    if (filteredPoints.length < 2) return filteredPoints;
    const p1 = filteredPoints[1];
    const p2 = filteredPoints[0];

    const newStart = _extendPointOnLine(p1, p2, dist);

    const extendedPoints = filteredPoints.slice(1);
    extendedPoints.unshift(newStart);
    return extendedPoints;
  };

  function getRandomTimestamp() {
    const randomDate = new Date(Math.random() * Date.now());
    return randomDate.getTime();
  }

  const CHARACTER_BOUNDS = [
    {
      x: 0,
      y: -124,
    },
    {
      x: 1024,
      y: 900,
    },
  ];
  const [from, to] = CHARACTER_BOUNDS;
  const preScaledWidth = to.x - from.x;
  const preScaledHeight = to.y - from.y;

  const positioner = (options) => {
    const { padding, width, height } = options;
    const effectiveWidth = width - 2 * padding;
    const effectiveHeight = height - 2 * padding;
    const scaleX = effectiveWidth / preScaledWidth;
    const scaleY = effectiveHeight / preScaledHeight;
    const scale = Math.min(scaleX, scaleY);
    const xCenteringBuffer = padding + (effectiveWidth - scale * preScaledWidth) / 2;
    const yCenteringBuffer = padding + (effectiveHeight - scale * preScaledHeight) / 2;
    return {
      padding,
      width,
      height,
      scale,
      xOffset: -1 * from.x * scale + xCenteringBuffer,
      yOffset: -1 * from.y * scale + yCenteringBuffer,
    };
  };

  const formarData = () => {
    const medians = data.value.medians;
    medians.forEach((item, index) => {
      const arr = [];
      item.forEach((el) => {
        const obj = {};
        obj.x = el[0];
        obj.y = el[1];
        arr.push(obj);
      });
      data.value.medians[index] = arr;
    });
    // createOrderWords(data.value.strokes);
  };

  const svgWordsDraw = () => {
    let path = ''
    data.value.strokes.forEach((s, i) => {
      const _pathLength = (getLength(data.value.medians[i]) + 200 / 2) + 20;
      const extendedMaskPoints = extendStart(data.value.medians[i], 200 / 2);
      const d = getPathString(extendedMaskPoints);
      path += `<path clip-path="url(#mask-${i + 1})" d="${d}" stroke="${config.wordsColor}" stroke-width="200" fill="none" stroke-linecap="round" stroke-linejoin="miter" stroke-dasharray="${_pathLength},${_pathLength}" style="opacity: 1; stroke-dashoffset: ${_pathLength};">
        <animate attributeName="stroke-dashoffset"
        from="${_pathLength}" to="0"
        dur="0.8s" repeatCount="1" begin="${i + 1.5}s" fill="freeze" />
        </path>
      `;
    });
    return path
  }

  const svgWordsPath = () => {
    let path = ''
    data.value.strokes.forEach((s, i) => {
      const _pathLength = (getLength(data.value.medians[i]) + 200 / 2) + 20;
      const extendedMaskPoints = extendStart(data.value.medians[i], 200 / 2);
      const d = getPathString(extendedMaskPoints);
      path += `<path clip-path="url(#mask-${i + 1})" d="${d}" stroke="${config.wordsColorDraw}" stroke-width="200" fill="none" stroke-linecap="round" stroke-linejoin="miter" stroke-dasharray="${_pathLength},${_pathLength}" style="opacity: 1; stroke-dashoffset: 0;"></path>`;
    });
    return path
  }

  const useDraw = (wordsData) => {
    data.value = wordsData
    // 格式化数据
    formarData(wordsData)
    return new Promise((resolve, reject) => {
      // 路径
      let path = "";
      // 剪裁
      let clipPath = "";
      data.value.strokes.forEach((p, i) => {
        clipPath += `<clipPath id="mask-${i + 1}"><path d="${p}"></path></clipPath>`;
      });
      // 配置
      const initDraw = positioner(config)

      let svgPath = `<svg id="${getRandomTimestamp()}" width="${initDraw.width}" height="${initDraw.height}" xmlns="http://www.w3.org/2000/svg" style="border: 10rpx solid #ddd; background-color: rgb(255, 255, 255);">
        <defs>${clipPath}</defs>
        <line x1="${initDraw.width/2}" y1="0" x2="${initDraw.width/2}" y2="${initDraw.width}" stroke-dasharray="12" stroke="#ddd"></line>
        <line x1="0" y1="${initDraw.width/2}" x2="${initDraw.width}" y2="${initDraw.width/2}" stroke-dasharray="12" stroke="#ddd"></line>
      `;
	  //<line x1="0" y1="0" x2="${initDraw.width}" y2="${initDraw.width}" stroke-dasharray="12" stroke="#ddd"></line>
      //<line x1="${initDraw.width}" y1="0" x2="0" y2="${initDraw.width}" stroke-dasharray="12" stroke="#ddd"></line>
      // 动画
      path += `<g transform="translate(${initDraw.xOffset}, ${initDraw.height - initDraw.yOffset}) scale(${initDraw.scale}, ${-1 * initDraw.scale})">${svgWordsPath()}</g>`
      path += `<g transform="translate(${initDraw.xOffset}, ${initDraw.height - initDraw.yOffset}) scale(${initDraw.scale}, ${-1 * initDraw.scale})">${svgWordsDraw()}</g>`
      
      // 底层

     
      svgPath += `${path}</svg>`;
      const baseSvg = "data:image/svg+xml;base64," + Base64.encode(svgPath);
      resolve(baseSvg)
    })
  };

  return {
    useDraw
  }
}
